package org.shj.spark.mlib.videolearn

import org.apache.log4j.{Level, Logger}
import org.apache.spark.{SparkConf, SparkContext}
import breeze.linalg._
import breeze.numerics._

object BreezeDemo {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setAppName("breeze")
    conf.setMaster("local")
    val sc = new SparkContext(conf)
    Logger.getRootLogger.setLevel(Level.WARN)
    
    // Breeze 创建函数示例
    val m1 = DenseMatrix.zeros[Double](2, 3)
    val v1 = DenseVector.zeros[Double](3)
    val v2 = DenseVector.ones[Double](3)
    val v3 = DenseVector.fill(3){5.0}
    val v4 = DenseVector.range(1, 10, 2)
    
    val m2 = DenseMatrix.eye[Double](3) // 3行3列的方阵，对角线(0,0),(1,1),(2,2)上的值均为 1.0，其余为 0.0
    val v6 = diag(DenseVector(1.0, 2.0, 3.0)) //类似上面的eye，只不过对角线上的3个值为指定的值
    val m3 = DenseMatrix((1.0, 2.0), (3.0, 4.0))
    val v8 = DenseVector(1, 2, 3, 4) // 1 行 4 列
    val v9 = DenseVector(1, 2, 3, 4).t // 4 行 1列
    val v10 = DenseVector.tabulate(3)(i => 2*i)
    val m4 = DenseMatrix.tabulate(3, 2)((i,j) => i+j)
    val v11 = new DenseVector(Array(1,2,3,4)) // 把数组转化成一维矩阵
    val m5 = new DenseMatrix(2,3, Array(1,2,3,4,5,6)) // 把数组转化成2行3列的矩阵
    val v12 = DenseVector.rand(4) //生成一个 1 行 4 列的矩阵，数值在0~1之间随机
    val m6 = DenseMatrix.rand(2,3) //生成一个 2 行 3 列的矩阵，数值在0~1之间随机
    
    //元素访问
    val a = DenseVector(1,2,3,4,5,6,7,8,9,10)
    a(0) //  1
    a(1 to 4) // DenseVector(2,3,4,5)
    a(5 to 1 by -1) // DenseVector(6,5,4,3,2)
    a(1 to -1) // DenseVector(2,3,4,5,6,7,8,9,10)
    a(-1) // 10
    
    m3(0,1) // 2.0
    m3(::, 1) // 所有行的第1列的数据 DenseVector(2.0, 4.0)
    
    //元素操作
    val m7 = DenseMatrix((1,2,3), (4,5,6))
    m7.reshape(3,2) // DenseMatrix((1,5), (4,3), (2,6))
    m7.toDenseVector
    
    val m8 = DenseMatrix((1,2,3), (4,5,6), (7,8,9))
    lowerTriangular(m8) // 取下三角，结果 为  1  0  0
                        //              4  5  0
                        //              7  8  9
    upperTriangular(m8) // 取上三角
    m8.copy
    diag(m8) // DenseVector(1, 5, 9)
    
    m8(::, 2) := 5  // 所有行的第2列赋值为 5
    m8(1 to 2, 1 to 2) := 5 //第1行到第2行，第1列到第2列 赋值为 5
    
    // DenseMatrix.vertcat(a1,a2) // a1和a2竖向联接， a1与a2须有相同的列数，
    // DenseMatrix.horzcat(a1,a2) // a1和a2横向联接，a1与a2须有相同的行数，
    
    
    // Breeze 数值计算函数
    val b = DenseMatrix((1,2,3), (4,5,6))
    val c = DenseMatrix((1,1,1), (2,2,2))
    
    b + c // 对应 位置元素相加
    b :* c
    b :/ c
    b :== c // 对应位置元素是否相等
    b :+= 3 // 所有元素加3
    b :*= 2 // 所有元素乘2
    max(b)
    argmax(b)
    
    
    // Breeze 加法
    sum(b)  // 所有元素相加
    sum(b, Axis._0)  // 每一列的所有元素相加，得到 DenseMatrix(5,7,9)
    sum(b, Axis._1)  // 每一行的所有元素相加，得到 DenseMatrix(6, 15)
    
    //trace(b) // 主对角线上的数字相加，必须是行数和列数相等的矩阵
    accumulate(DenseVector(1,2,3,4)) // 各项累加，结果是： DenseVector(1,2,6,10)
    
    
    // Breeze 布尔函数
    val b1 = DenseVector(true, false, true)
    val b2 = DenseVector(false, true, true)
    
    b1 :& b2 // DenseVector(false, false, true)
    !b1 // 取反    DenseVector(false, true, false)
    
    val b3 = DenseVector(1, 0, 2)
    println("any(b3): ", any(b3)) // 有不为0的数， 结果为 true
    println("all(b3): ", all(b3)) // 都不为0的数， 结果为 false
    
    
    // 线性代数函数
    val a4 = DenseMatrix((1.0, 2.0, 3.0), (4.0, 5.0, 6.0), (7.0, 8.0, 9.0))
    val b4 = DenseMatrix((1.0, 1.0, 1.0), (1.0, 1.0, 1.0), (1.0, 1.0, 1.0))
    println("a4 / b4 ==> ")
    println(a4 / b4)
    
    println("det(a4) ==> ")
    println(det(a4))  // 求行列式
    
    inv(a4) // 求逆
    pinv(a4) // 求伪逆
    
    val svd.SVD(u, s, v) = svd(a4)  // SVD 分解
    
    
    // Breeze 取整函数
    val a5 = DenseVector(1.3, 3.6, -2.7, 0)
    println("round(a5)", round(a5))
    println("ceil(a5)", ceil(a5))
    println("floor(a5)", floor(a5))
    println("signum(a5)", signum(a5))  // 正负号函数，正值返回1，负值返回 -1
    println("abs(a5)", abs(a5))
    
  }
}